﻿using System;
using System.Collections.Generic;
using System.Text;

namespace NMbsDuplex.TCPServerX.Deamon
{
    using Node;
    using System.Linq;
    using System.Net.Sockets;

    #region typeDef 定义函数指针 数据结构
    public delegate NodesUser DuplexEvent(Socket sockFD);   // .NET C#
    public delegate bool MQTTHandler(Socket sockRef, string UnPackagedMsg);
    //typeDef void(^Block)(Socket* fd); // Objective-C
    // void(*ptrFunction)(Socket* fd); // C C++
    // $.SendAsync($Function) { ... }) // JavaScript PHP Python
    #endregion

    public enum workItemTags
    {
        NodeLocating, NodeLargen, NodeSqueeze
    }

    public class TCPBase
    {
        #region Core - 内核属性
        /// 进程级 Socket 文件描述符
        protected Socket Listener;
        /* 函数指针字典 */
        protected Dictionary<workItemTags, DuplexEvent> RegisterDict4Domain;
        /* TCP传输最大缓冲区尺寸 */
        static internal int BUFSIZ { get { return short.MaxValue / 4; } }
        /* 默认最大用户数量200个 */
        static internal int MaxNodesCount;
        /* 系统在线人数上限 */
        static internal int ManagedQueueLength;
        /* 最短推送间隔 1.5秒 */
        protected virtual TimeSpan PushInterval { get { return TimeSpan.FromSeconds(0.618); } }
        /* Socket默认编码方式 */
        protected virtual Encoding TXTCoding { get { return Encoding.UTF8; } }
        #endregion

        private TCPBase() {  /*封闭构造方法*/ }
        /// 通过指派一个端口号进行公共基类的初始化
        protected TCPBase(int BootWithPort = 33036)
        {
            MaxNodesCount = 20;
            ManagedQueueLength = (int)(MaxNodesCount * 0.75);
            Listener = new Socket(
                AddressFamily.InterNetwork,
                SocketType.Stream,
                ProtocolType.Tcp
            );
            #region 域用户管理
            /* 遍历节点链表 根据文件描述符查找用户节点 */
            DuplexEvent T1 = SockRef =>
            {
                // 链表遍历 复杂度 N
                return LinkedInUsers.Where(node => node.Value.refSock == SockRef)
                        .FirstOrDefault().Value;
            };
            /* 添加节点完成之后 ~ 总是返回链表最后一个节点用户 */
            DuplexEvent T2 = SockRef =>
            {
                var node = new NodesUser(SockRef);
                Console.WriteLine(node);
                LinkedInUsers.AddLast(new LinkedListNode<NodesUser>(node));
                Console.WriteLine("当前在线人数 ---> [{0}]", LinkedInUsers.Count);
                return LinkedInUsers.Last().Value;
            };
            // 遍历链表节点 删除节点用户
            DuplexEvent T3 = SockRef =>
            {
                Console.WriteLine("客户端[{0}]强制申请断开", SockRef.LocalEndPoint);
                NodesUser mayExists = LinkedInUsers.First().Value;
                LinkedInUsers.ToList().ForEach(item =>
                {
                    var user = item as LinkedListNode<NodesUser>;
                    if (item.Value.refSock == SockRef)
                    {
                        user.Value.isDone = true;
                        Console.WriteLine("删除`用户链表`节点 标记用户为[isOver]...");
                        SockRef.Close();
                        if (LinkedInUsers.Remove(user))
                        {
                            mayExists = user.Value;
                        }
                    }
                    Console.WriteLine("当前在线人数 ---> [{0}]", LinkedInUsers.Count);
                });
                return mayExists;
            };
            #endregion
            /* 注入函数指针字典 */
            RegisterDict4Domain = new Dictionary<workItemTags, DuplexEvent> {
                { workItemTags.NodeLocating, T1 },
                { workItemTags.NodeLargen  , T2 },
                { workItemTags.NodeSqueeze , T3 },
            };

        }
        #region 处理基本用户消息队列入栈
        protected internal virtual bool BLLGo(Socket refSock, string receivingMsg)
        {
            NodesUser userInfo = RegisterDict4Domain[workItemTags.NodeLocating](refSock);
            userInfo.MsgLogs.Add(receivingMsg);
            MsgQueue.Enqueue(userInfo);

            return !string.IsNullOrEmpty(userInfo.UserName);
        }
        #endregion
        protected internal void BootStrap4LogSys()
        {
            Console.WriteLine("Success booting System~[服务器启动成功...]");
            Console.WriteLine("Listen:[{0}]---> " + Listener.LocalEndPoint);
            Console.WriteLine("AddressFamily ---> " + Listener.AddressFamily);
            Console.WriteLine("SocketType ---> " + Listener.SocketType);
            Console.WriteLine("ProtocolType ---> " + Listener.ProtocolType);
            Console.WriteLine("EnCoding.WebName ---> " + TXTCoding.WebName);
            Console.WriteLine("BUFSIZ ---> " + BUFSIZ);
            Console.WriteLine("--------------------------------------");
        }

        #region Const - 内核常量区
        internal const string GREETING = "`非阻断式`[丁诚昊双工Serv] - 2017.11.15";
        #endregion

        #region CoreData - 内核数据结构
        /// <summary>
        /// 1.链表LinkedListNodes 管理用户
        /// </summary>
        private Lazy<LinkedList<LinkedListNode<NodesUser>>> _LinkedInUsers =
            new Lazy<LinkedList<LinkedListNode<NodesUser>>>(() =>
            {
                Console.WriteLine("\t ~~~~  ~~~~  ~~~~  ~~~~  ~~~~ ");
                Console.WriteLine("\t[用户链表]激活 节点数 ");
                Console.WriteLine("\t ~~~~  ~~~~  ~~~~  ~~~~  ~~~~ ");
                return new LinkedList<LinkedListNode<NodesUser>>();
            }, true);
        internal LinkedList<LinkedListNode<NodesUser>> LinkedInUsers
        {
            get { return _LinkedInUsers.Value; }
        }
        /// <summary>
        /// Queue _神经节点消息队列
        /// </summary>
        private Lazy<Queue<NodesUser>> _MsgNodesInfoQueue = new Lazy<Queue<NodesUser>>(() =>
        {
            Console.WriteLine("\t ~~~~  ~~~~  ~~~~  ~~~~  ~~~~ ");
            Console.WriteLine("\t[消息队列]激活 节点数");
            Console.WriteLine("\t ~~~~  ~~~~  ~~~~  ~~~~  ~~~~ ");
            return new Queue<NodesUser>();
        }, true /* 暂不考虑线程安全 */ );
        internal Queue<NodesUser> MsgQueue { get { return _MsgNodesInfoQueue.Value; } }
        #endregion
    }
}
